﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace QRCodeTools {

    public class ScreenSize {
        public string DeviceName { get; set; }
        /// <summary>
        /// 原始分辨率
        /// </summary>
        public Rectangle RawBounds { get; set; }
        /// <summary>
        /// 实际分辨率
        /// </summary>
        public Rectangle Bounds { get; set; }
    }
    public static class ScreenHelper {
        #region Win32 API

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool SetProcessDPIAware();


        [DllImport("user32.dll")]
        static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);

        [StructLayout(LayoutKind.Sequential)]
        struct DEVMODE {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;

            public short dmOrientation;
            public short dmPaperSize;
            public short dmPaperLength;
            public short dmPaperWidth;

            public short dmScale;
            public short dmCopies;
            public short dmDefaultSource;
            public short dmPrintQuality;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string dmFormName;
            public short dmLogPixels;
            public short dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;

            public int dmDisplayFlags;
            public int dmDisplayFrequency;

            public int dmICMMethod;
            public int dmICMIntent;
            public int dmMediaType;
            public int dmDitherType;
            public int dmReserved1;
            public int dmReserved2;

            public int dmPanningWidth;
            public int dmPanningHeight;
        };
        #endregion


        public static List<ScreenSize> AllScreenSizes { get; }

        static ScreenHelper() {
            AllScreenSizes = Screen.AllScreens.Select(s => new ScreenSize {
                DeviceName = s.DeviceName,
                Bounds = s.Bounds,
                RawBounds = GetScreenRawBounds(s),
            }).ToList();
        }

        /// <summary>
        /// 获取屏幕原始的分辨率大小(不受系统显示缩放设置影响,设置-显示设置-缩放与布局-更改文本、应用等项目的大小)
        /// </summary>
        /// <param name="screen"></param>
        /// <returns></returns>
        public static Size GetScreenRawResolution(Screen screen) {
            DEVMODE dev = new DEVMODE();
            var modeNum = -1;
            var tryCount = 0;
            while (!EnumDisplaySettings(screen.DeviceName, modeNum, ref dev) && tryCount < 10) {
                modeNum++;
                tryCount++;
            }
            return new Size(dev.dmPelsWidth, dev.dmPelsHeight);
        }
        /// <summary>
        /// 获取屏幕原始的分辨率大小(不受系统显示缩放设置影响,设置-显示设置-缩放与布局-更改文本、应用等项目的大小)
        /// </summary>
        /// <param name="screen"></param>
        /// <returns></returns>
        public static Rectangle GetScreenRawBounds(Screen screen) {
            DEVMODE dev = new DEVMODE();
            var modeNum = -1;
            var tryCount = 0;
            while (!EnumDisplaySettings(screen.DeviceName, modeNum, ref dev) && tryCount < 10) {
                modeNum++;
                tryCount++;
            }
            var scale = (double)dev.dmPelsWidth /screen.Bounds.Width;
            return new Rectangle(
                (int)(screen.Bounds.X * scale),
                (int)(screen.Bounds.Y * scale), 
                dev.dmPelsWidth, 
                dev.dmPelsHeight);
        }


        /// <summary>
        /// 查询点在哪个屏幕,会自动适应缩放
        /// </summary>
        /// <param name="pos"></param>
        /// <returns></returns>
        public static ScreenSize PosInScreen(Point pos) {
            return AllScreenSizes.FirstOrDefault(s => s.RawBounds.Contains(pos));
        }

    }
}
